package com.franklin.java.utils;

import com.franklin.java.api.psi.data.PsiData;
import com.franklin.plugins.common.collection.PrettyArrayList;
import com.franklin.plugins.common.utils.StringHelper;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.psi.PsiClass;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
import org.apache.commons.lang.ArrayUtils;

import java.util.*;

/**
 * 模块工具类
 * @author Franklin
 * @since 2021/09/19 09:48
 */
public abstract class ModuleUtils {

    public static PsiClass findAbstractMethodImplementClass(PsiData targetData, String callMethodName) {
        PsiShortNamesCache psiShortNamesCache = PsiShortNamesCache.getInstance(targetData.getPsiElement().getProject());
        return Optional.ofNullable(ModuleUtil.findModuleForPsiElement(targetData.getPsiElement()))
                .map(module -> {
                    GlobalSearchScope globalSearchScope = GlobalSearchScope.moduleScope(module);
                    return PsiUtils.getPsiClass(targetData, callMethodName, psiShortNamesCache, globalSearchScope);
                })
                .orElse(PsiUtils.findAbstractMethodImplementClass(targetData, callMethodName));
    }

    public static PsiClass findClassByQualifiedOrSimpleName(Module module, String path, String typeQualifiedOrSimpleName){
        if (typeQualifiedOrSimpleName.contains(".")){
            return findClass(module, path, typeQualifiedOrSimpleName);
        }
        return findClassBySimpleName(module, path, typeQualifiedOrSimpleName);
    }

    public static PsiClass findClass(Module module,String path,String typeQualifiedName){
        String[] names = typeQualifiedName.split("\\.");
        PsiClass[] psiClasses = findClasses(module,names[names.length - 1]);
        if (ArrayUtils.isEmpty(psiClasses)){
            return null;
        }
        List<PsiClass> candidateClasses = new PrettyArrayList<>();
        for (PsiClass psiClass : psiClasses) {
            if (StringHelper.equals(psiClass.getQualifiedName(),typeQualifiedName)){
                candidateClasses.add(psiClass);
            }
        }
        return PsiUtils.findClassNearby(typeQualifiedName, path, candidateClasses);
    }

    public static PsiClass findClassBySimpleName(Module module,String path,String typeSimpleName){
        typeSimpleName = StringHelper.firstToUpperCase(typeSimpleName);
        PsiClass[] psiClasses = findClasses(module,typeSimpleName);
        if (ArrayUtils.isEmpty(psiClasses)){
            return null;
        }
        List<PsiClass> candidateClasses = new PrettyArrayList<>();
        Collections.addAll(candidateClasses,psiClasses);
        return PsiUtils.findClassNearby(typeSimpleName, path, candidateClasses);
    }

    public static PsiClass[] findClasses(Module module, String typeName){
        PsiShortNamesCache psiShortNamesCache = PsiShortNamesCache.getInstance(module.getProject());
        GlobalSearchScope globalSearchScope = GlobalSearchScope.moduleScope(module);
        return psiShortNamesCache.getClassesByName(typeName,globalSearchScope);
    }

}
